package com.xsomnus.rpc.consumer.config.rpc;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Set;

/**
 * @author @xsomnus666_xiawenye★
 * @since 2019/4/22 0022 17:48
 * 当你发现自己的才华撑不起野心时，就请安静下来学习吧
 */
public class ClassPathRPCScanner extends ClassPathBeanDefinitionScanner {

    private RPCFactoryBean<?> rpcFactoryBean = new RPCFactoryBean<Object>();

    private Class<? extends Annotation> annotationClass;

    public ClassPathRPCScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }


    public void setAnnotationClass(Class<? extends Annotation> annotationClass) {
        this.annotationClass = annotationClass;
    }

    public void registerFilters() {

        boolean acceptAllInterface = true;

        // 选择特定的添加了注解的类
        if (this.annotationClass != null) {
            addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
            acceptAllInterface = false;
        }

        // 添加所有的类
        if (acceptAllInterface) {
            addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
        }

        // 去掉 package-info.java
        addExcludeFilter(((metadataReader, metadataReaderFactory) -> {
            String className = metadataReader.getClassMetadata().getClassName();
            return className.endsWith("package-info");
        }));

    }

    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        if (beanDefinitions.isEmpty()) {
            logger.warn("在[" + Arrays.toString(basePackages) + "]文件夹下没有发现对应的RPC服务的包, 请检查你的配置");
        } else {
            processBeanDefinitions(beanDefinitions);
        }
        return beanDefinitions;
    }

    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitionHolders) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitionHolders) {
            definition = (GenericBeanDefinition) holder.getBeanDefinition();
            definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
            definition.setBeanClass(this.rpcFactoryBean.getClass());
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            logger.debug("holder: " + holder);
        }
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }
}
